package com.xuexiang.keycodelistener;

import android.os.Handler;
import android.os.Looper;

import java.io.File;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * 按键事件监听
 *
 * @author xuexiang
 * @since 2019/1/9 下午3:43
 */
public class KeyEventManager {

    private List<WeakReference<KeyEventSubscriber>> mSubscribers;

    private Handler mMainHandler;

    private static volatile KeyEventManager sInstance = null;

    private String mInputEventPath;
    /**
     * 默认是10011110(158)，其实只要大于0就行了
     */
    private int mScanCode = 0x9e;

    static {
        System.loadLibrary("keyevent-lib");
    }

    private KeyEventManager() {
        mSubscribers = new ArrayList<>();
        mMainHandler = new Handler(Looper.getMainLooper());

        if (new File("/system/lib64").exists()) {
            mInputEventPath = "/dev/input/event1";
        } else {
            mInputEventPath = "/dev/input/event0";
        }
    }

    /**
     * 获取单例
     *
     * @return
     */
    public static KeyEventManager getInstance() {
        if (sInstance == null) {
            synchronized (KeyEventManager.class) {
                if (sInstance == null) {
                    sInstance = new KeyEventManager();
                }
            }
        }
        return sInstance;
    }

    private native int startKeyScan(String path, int code);

    private native void stopKeyScan();


    /**
     * JNI通知按键事件的方法
     *
     * @param keyCode
     */
    private void onKeyDown(int keyCode) {
        notifyKeyEvent(keyCode);
    }

    /**
     * 通知KeyEvent
     *
     * @param keyCode
     */
    private void notifyKeyEvent(final int keyCode) {
        Iterator<WeakReference<KeyEventSubscriber>> it = mSubscribers.iterator();
        synchronized (it) {
            while (it.hasNext()) {
                final KeyEventSubscriber subscriber = it.next().get();
                if (subscriber != null) {
                    mMainHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            subscriber.onKeyDown(keyCode);
                        }
                    });
                } else {
                    it.remove();
                }
            }
        }
    }

    /**
     * 注册按键事件的订阅者
     *
     * @param subscriber 事件订阅者
     */
    public boolean registerKeyEventSubscriber(KeyEventSubscriber subscriber) {
        if (subscriber != null) {
            if (mSubscribers.size() == 0) {
                startKeyScan(mInputEventPath, mScanCode);
            }
            WeakReference<KeyEventSubscriber> obs = new WeakReference<>(subscriber);
            return mSubscribers.add(obs);
        } else {
            return false;
        }
    }


    /**
     * 注销按键事件的订阅者
     *
     * @param subscriber 事件订阅者
     */
    public boolean unregisterKeyEventSubscriber(KeyEventSubscriber subscriber) {
        boolean result = false;
        if (subscriber != null) {
            Iterator<WeakReference<KeyEventSubscriber>> it = mSubscribers.iterator();
            synchronized (it) {
                while (it.hasNext()) {
                    KeyEventSubscriber sb = it.next().get();
                    if (sb == subscriber) {
                        it.remove();
                        result = true;
                        break;
                    }
                }
            }
        }
        if (mSubscribers.size() == 0) {
            stopKeyScan();
        }
        return result;
    }

    /**
     * 注销所有的推送消息的订阅者
     */
    public void unregisterAllSubscribers() {
        if (mSubscribers != null) {
            mSubscribers.clear();
            stopKeyScan();
        }
    }

    /**
     * 按键事件订阅
     */
    public interface KeyEventSubscriber {
        /**
         * 通知KeyEvent
         *
         * @param keyCode 注意这里的keyCode和系统onKeyDown返回的值是不同的
         */
        void onKeyDown(int keyCode);
    }
}
